/**
 * @module      高级table
 * @author      nayo
 * @date        2020/9/24 10:46 上午
 * @version     1.0
 */

import Grid from 'vxe-table/packages/grid/src/grid'
import RotStorage from 'rot-storage/dist/rot-storage';
import Sortable from 'sortablejs';
import XEUtils from 'xe-utils'

let db = new RotStorage.RotStorage({drive: new RotStorage.drive.IndexedDB('storage', 'table')});

const getKey = (key) => {
	return 'tx-' + key;
}

export default {
	name: 'MdAdvancedTable',
	extends: Grid,
	props: {
		isColumnDrop: Boolean,
		isRowDrop: Boolean,
		rowDropMoveHook: Function
	},
	data() {
		return {
			tempColumns: this.$utils.deepCopy(this.columns),
			colSortable: undefined,
			rowSortable: undefined
		}
	},
	created() {
		this.getTempColumns();
	},
	mounted() {
		this.$refs.xTable.$on('resizable-change', this.onResizableChange)
		this.$on('custom', this.onResizableChange)
	},
	beforeDestroy() {
		this.$refs.xTable.$off('resizable-change', this.onResizableChange)
		this.$off('custom', this.onResizableChange);
		this.colSortable && this.colSortable.destroy();
		this.rowSortable && this.rowSortable.destroy();
	},
	methods: {
		onResizableChange() {
			this.saveDB();
		},
		getTempColumns() {
			if (this.id) {
				db.get(getKey(this.id)).then(data => {
					if (data) {
						this.createdNewColumns(data);
					}
					this.tableDrop();
				}).catch(() => {
					this.tableDrop();
				});
			} else {
				this.tableDrop();
			}
		},
		createdNewColumns(data = {}) {
			let tempObj = {};
			let newColumns = [];

			this.tempColumns.forEach(item => {
				tempObj[item.field] = this.$utils.deepCopy(item);
			});

			for (let key in data) {
				if (tempObj[key]) {
					tempObj[key].width = data[key].width;
					tempObj[key].visible = data[key].visible;
					newColumns.push(tempObj[key]);
					delete tempObj[key];
				}
			}
			for (let key in tempObj) {
				newColumns.push(tempObj[key]);
			}
			this.tempColumns = newColumns;
		},
		tableDrop() {
			this.isColumnDrop && this.columnDrop();
			this.isRowDrop && this.rowDrop();
		},
		columnDrop() {
			this.$nextTick(() => {
				this.colSortable = Sortable.create(this.$el.querySelector('.body--wrapper>.vxe-table--header .vxe-header--row'), {
					handle: '.vxe-header--column:not(.col--fixed)',
					onEnd: ({newIndex, oldIndex}) => {
						let {visibleColumn} = this.getTableColumn();
						oldIndex = findColumnsIndex(this.tempColumns, visibleColumn[oldIndex].property);
						newIndex = findColumnsIndex(this.tempColumns, visibleColumn[newIndex].property);
						let currRow = this.tempColumns.splice(oldIndex, 1)[0];
						this.tempColumns.splice(newIndex, 0, currRow);
						this.$emit('sortable', this);
						this.$nextTick(() => {
							this.saveDB();
						});
					}
				});
			});
		},
		rowDrop() {
			this.$nextTick(() => {
				this.rowSortable = Sortable.create(this.$el.querySelector('.body--wrapper>.vxe-table--body tbody'), {
					handle: '.drag-btn',
					onEnd: (e) => {
						let {item, oldIndex, newIndex} = e
						const options = {children: 'children'}
						const targetTrElem = item
						const wrapperElem = targetTrElem.parentNode
						const prevTrElem = targetTrElem.previousElementSibling
						const tableTreeData = this.data;
						const selfRow = this.getRowNode(targetTrElem).item
						const selfNode = XEUtils.findTree(tableTreeData, row => row === selfRow, options)
						if (prevTrElem) {
							// 移动到节点
							const prevRow = this.getRowNode(prevTrElem).item
							const prevNode = XEUtils.findTree(tableTreeData, row => row === prevRow, options)
							if (XEUtils.findTree(selfRow[options.children], row => prevRow === row, options)) {
								// 错误的移动
								const oldTrElem = wrapperElem.children[oldIndex]
								wrapperElem.insertBefore(targetTrElem, oldTrElem)
								return this.$XModal.message({content: '不允许自己给自己拖动！', status: 'error'})
							}
							const currRow = selfNode.items.splice(selfNode.index, 1)[0]
							if (this.isTreeExpandByRow(prevRow)) {
								// 移动到当前的子节点
								prevRow[options.children].splice(0, 0, currRow)
							} else {
								// 移动到相邻节点
								prevNode.items.splice(prevNode.index + (selfNode.index < prevNode.index ? 0 : 1), 0, currRow)
							}
							this.$emit('row-drop', {oldIndex, newIndex, data: tableTreeData, prevRow, selfNode});
						} else {
							// 移动到第一行
							const currRow = selfNode.items.splice(selfNode.index, 1)[0]
							tableTreeData.unshift(currRow)
							this.$emit('row-drop', {oldIndex, newIndex, data: tableTreeData, selfNode});
						}
						// 如果变动了树层级，需要刷新数据
						// this.tableTreeData = [...tableTreeData]
					},
					sort: true,
					onMove: (evt, originalEvent) => {
						if (this.rowDropMoveHook instanceof Function) {
							return this.rowDropMoveHook(evt, originalEvent)
						}
						return true;
					},
				})
			})
		},
		saveDB() {
			let {collectColumn} = this.getTableColumn();
			let obj = {};
			collectColumn.forEach((item, index) => {
				let width = item.resizeWidth || item.width;
				obj[this.tempColumns[index].field] = {width, visible: item.visible};
				this.tempColumns[index].width = width;
				this.tempColumns[index].visible = item.visible;
			});
			if (this.id) db.set(getKey(this.id), obj);
		}
	},
	watch: {
		tempColumns: {
			handler() {
				this.$nextTick(() => {
					this.loadColumn(this.tempColumns);
				})
			},
			deep: true,
			immediate: true
		}
	}
};

/**
 *
 * @param columns {[{field:String}]}
 * @param field
 * @returns {number}
 */
function findColumnsIndex(columns, field) {
	let index = -1;
	columns.forEach((item, i) => {
		if (item.field === field) {
			index = i;
		}
	})
	return index;
}
